Skip to content

feat: add openai and claude structured output config#5763

Merged
forestileao merged 9 commits into
superplanehq:mainfrom
WashingtonKK:ai/structured-output
Jul 2, 2026
Merged

feat: add openai and claude structured output config#5763
forestileao merged 9 commits into
superplanehq:mainfrom
WashingtonKK:ai/structured-output

Conversation

@WashingtonKK

Copy link
Copy Markdown
Collaborator

Summary

This adds structured output as a configuration option for the following components:

  • claude.textPrompt
  • openai.textPrompt

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
@superplanehq-integration

Copy link
Copy Markdown

👋 Commands for maintainers:

  • /sp start - Start an ephemeral machine (takes ~30s)
  • /sp stop - Stop a running machine (auto-executed on pr close)

Comment thread pkg/integrations/claude/text_prompt.go
@superplane-gh-integration-9000

superplane-gh-integration-9000 Bot commented Jun 29, 2026

Copy link
Copy Markdown

Risk: 35/100 (low)

Summary

Adds JSON Schema-constrained structured output support to both OpenAI and Claude text-prompt components, including shared validation/normalization logic, provider API wiring, frontend canvas badges, and a general autosave fix for togglable fields.

Concerns

  • Frontend hasSchema() only checks string is non-empty; invalid JSON still shows the 'Structured output' badge.
  • JSON parse failures on the provider response are silently swallowed; no error is surfaced to users.
  • SettingsTab autosave change affects all togglable fields—unintended side effects possible beyond structured output.
  • Claude output_config structured output may require an anthropic-beta header; no beta flag is added to requests.
  • Response JSON is not validated against the user's schema; a non-conforming response silently leaves parsed null.
  • Expression-based schemas bypass setup-time validation; a bad template could only fail at run time.

Recommended reviewers: forestileao

…chema

Addresses Cursor Bugbot review on PR superplanehq#5763: claude.textPrompt Setup only
checked the schema root was an object, while the field description and docs
require every object to set additionalProperties:false (an Anthropic
requirement). Such schemas passed Setup and failed later at the Claude API,
unlike openai.textPrompt which rejects them at Setup.

Add validateClaudeOutputSchema: a recursive check that every object sets
additionalProperties:false (walking properties, items, anyOf/allOf/oneOf,
$defs). It intentionally does NOT require all properties in "required" —
Anthropic permits optional fields, unlike OpenAI strict mode.

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
Set node-level metadata in Setup for claude.textPrompt and openai.textPrompt
so the configured model, max tokens (Claude), and whether structured output
is enabled are visible on the node in the UI without opening its config.
Mirrors the existing node-metadata pattern (e.g. digitalocean IndexKB).

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
Comment thread pkg/integrations/openai/structured_output.go Outdated
Replace the raw JSON Schema input on claude.textPrompt and openai.textPrompt
with a guided builder: users define output fields (name, type, description,
required) including nested objects and lists, and the backend assembles the
JSON Schema. Provider rules are handled automatically -- Anthropic omits
optional fields from "required"; OpenAI strict mode lists every field and
makes optional ones nullable. Shared logic lives in the new
pkg/integrations/structuredoutput package.

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
Replace the guided field builder with a JSON Schema the user edits directly. The
Structured Output field is now a togglable JSON text area pre-filled with an
editable default schema, validated before the request is fired (valid JSON, a
JSON object, object root with non-empty properties).

The schema is normalized to provider constraints on send: every object gets
additionalProperties:false, and OpenAI strict mode additionally forces all
properties into required. Claude keeps required as written.

Update both text prompt components, the node-metadata flag, the frontend
mappers, and regenerate component docs.

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
Comment thread pkg/configuration/structuredoutput/structuredoutput.go
Enabling a togglable field only stored its value in local state until a
save-on-blur field type (e.g. a text field pre-filled with a default) was
blurred. A run or reload before that persisted config without the value, so a
component like the structured-output schema showed as enabled but was silently
skipped. Trigger autosave on the off->on transition of a togglable field.

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
Comment thread web_src/src/pages/app/mappers/claude/base.ts
The canvas node tile computed the badge as
meta?.structuredOutput ?? hasSchema(config?.outputSchema), so a stale persisted
metadata flag (autosave updates configuration only) kept the badge visible after
structured output was cleared or disabled. Derive it from the live configuration
instead, falling back to metadata only when no configuration is present.

Also run prettier on SettingsTab.tsx so make check.format.js passes.

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
Comment thread pkg/configuration/structuredoutput/structuredoutput.go
Comment thread pkg/configuration/structuredoutput/structuredoutput.go
The structured-output helpers build configuration fields and JSON schemas for
integrations rather than being an integration themselves, so per review they do
not belong under pkg/integrations. Move the package to
pkg/configuration/structuredoutput (alongside the existing
pkg/configuration/expressionvalidation helper) and update the claude and openai
text prompt imports.

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e5f5900. Configure here.

Comment thread pkg/integrations/claude/text_prompt.go
The structured-output schema field supports expressions like the prompt field,
but Setup parsed the stored value as literal JSON, so a schema containing an
unresolved {{ ... }} expression failed config-time validation even though it
would resolve to valid JSON at execution. Skip JSON validation in Setup when the
schema still contains an expression; Execute re-parses the resolved value.

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
@forestileao

Copy link
Copy Markdown
Collaborator

👍

@forestileao forestileao merged commit e5fe57d into superplanehq:main Jul 2, 2026
6 checks passed
usernamenenad pushed a commit to usernamenenad/superplane that referenced this pull request Jul 5, 2026
Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants